#include "TcpServer.h"
#include "Acceptor.h"
#include "EventLoop.h"
#include "Logger.h"
#include <cstdio>  

using namespace xop;
using namespace std;

TcpServer::TcpServer(EventLoop* event_loop)
	: event_loop_(event_loop)
	, port_(0)
	, acceptor_(new Acceptor(event_loop_))
	, is_started_(false)
{
    //虽然回调函数(lambda表达式)是在父类中设置的，但是this指针并不会和父类绑定，如果是子类触发回调时，this是指向子类对象的
	acceptor_->SetNewConnectionCallback([this](SOCKET sockfd) {//当RtmpServer调用这个回调函数时，this指向的是RtmpServer
		TcpConnection::Ptr conn = this->OnConnect(sockfd);//当RtmpServer调用这个回调函数时，调用的是RtmpServer中的OnConnect
		if (conn) {
            //将新的网络连接添加到容器中，智能指针作为函数参数，当传递指针对象，而不是对象的引用时，才能利用智能指针的引用计数和内存回收能力
			this->AddConnection(sockfd, conn);
			conn->SetDisconnectCallback([this](TcpConnection::Ptr conn) {
				auto scheduler = conn->GetTaskScheduler();//可以认为智能指针是一种指针对象，即管理指针的对象，它重载了指针运算符
				SOCKET sockfd = conn->GetSocket();//指针对象的析构函数负责销毁指针及其资源(例如在函数调用结束，销毁局部变量时)，实际上，智能指针是指针对象的模板，
                //触发删除或者定时删除
				if (!scheduler->AddTriggerEvent([this, sockfd] {this->RemoveConnection(sockfd); })) {
					scheduler->AddTimer([this, sockfd]() {this->RemoveConnection(sockfd); return false; }, 100);
				}
			});
		}
	});
}

TcpServer::~TcpServer()
{
	Stop();
}

bool TcpServer::Start(std::string ip, uint16_t port)
{
	Stop();

	if (!is_started_) {
		if (acceptor_->Listen(ip, port) < 0) {
			return false;
		}

		port_ = port;
		ip_ = ip;
		is_started_ = true;
		return true;
	}

	return false;
}

void TcpServer::Stop()
{
	if (is_started_) {		
		mutex_.lock();
		for (auto iter : connections_) {
			iter.second->Disconnect();
		}
		mutex_.unlock();

		acceptor_->Close();
		is_started_ = false;

		while (1) {
			Timer::Sleep(10);
			if (connections_.empty()) {
				break;
			}
		}
	}	
}

TcpConnection::Ptr TcpServer::OnConnect(SOCKET sockfd)
{
    //make_shared模板函数  语法： std::shared_ptr<T>  std::make_shared<T>(Args&&... args);
    //shared_ptr智能指针get()方法，获取智能指针包装的原始指针
	return std::make_shared<TcpConnection>(event_loop_->GetTaskScheduler().get(), sockfd);
}

void TcpServer::AddConnection(SOCKET sockfd, TcpConnection::Ptr tcpConn)
{
	std::lock_guard<std::mutex> locker(mutex_);
	connections_.emplace(sockfd, tcpConn);
}

void TcpServer::RemoveConnection(SOCKET sockfd)
{
	std::lock_guard<std::mutex> locker(mutex_);
	connections_.erase(sockfd);
}
